<html>

<head>
  <title>Accessible events testing for document</title>

  <link rel="stylesheet" type="text/css"
        href="chrome://mochikit/content/tests/SimpleTest/test.css" />

  <script type="application/javascript"
          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>

  <script type="application/javascript"
          src="../common.js"></script>
  <script type="application/javascript"
          src="../role.js"></script>
  <script type="application/javascript"
          src="../states.js"></script>

  <script type="application/javascript">
    // Front end stuff sometimes likes to stuff things in the hidden window(s)
    // in which case there's accessibles for that content.
    Components.utils.import("resource://gre/modules/Services.jsm");

    // Force the creation of an accessible for the hidden window's document.
    var doc = Services.appShell.hiddenDOMWindow.document;
    gAccService.getAccessibleFor(doc);

    // The private hidden window will be lazily created that's why we need to do
    // it here *before* loading '../events.js' or else we'll have a duplicate
    // reorder event.
    var privateDoc = Services.appShell.hiddenPrivateDOMWindow.document;

    // Force the creation of an accessible for the private hidden window's doc.
    gAccService.getAccessibleFor(privateDoc);
  </script>

  <script type="application/javascript"
          src="../events.js"></script>

  <script type="application/javascript">
    ////////////////////////////////////////////////////////////////////////////
    // Invokers

    function changeIframeSrc(aIdentifier, aURL)
    {
      this.DOMNode = getNode(aIdentifier);

      this.eventSeq = [
        new invokerChecker(EVENT_REORDER, getAccessible(this.DOMNode)),
        new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getIframeDoc)
      ];

      this.invoke = function changeIframeSrc_invoke()
      {
        this.DOMNode.src = aURL;
      }

      this.finalCheck = function changeIframeSrc_finalCheck()
      {
        var accTree = {
          role: ROLE_INTERNAL_FRAME,
          children: [
            {
              role: ROLE_DOCUMENT,
              name: aURL == "about:" ? "About:" : aURL
            }
          ]
        };

        testAccessibleTree(this.DOMNode, accTree);
      }

      this.getID = function changeIframeSrc_getID()
      {
        return "change iframe src on " + aURL;
      }

      function getIframeDoc()
      {
        return getAccessible(getNode(aIdentifier).contentDocument);
      }
    }

    const kHide = 1;
    const kShow = 2;
    const kRemove = 3;
    function morphIFrame(aIdentifier, aAction)
    {
      this.DOMNode = getNode(aIdentifier);
      this.IFrameContainerDOMNode = this.DOMNode.parentNode;

      this.eventSeq = [];

      var checker = null;
      if (aAction == kShow)
        checker = new invokerChecker(EVENT_SHOW, this.DOMNode);
      else
        checker = new invokerChecker(EVENT_HIDE, this.DOMNode);
      this.eventSeq.push(checker);

      var reorderChecker =
        new invokerChecker(EVENT_REORDER, this.IFrameContainerDOMNode);
      this.eventSeq.push(reorderChecker);

      this.invoke = function morphIFrame_invoke()
      {
        if (aAction == kHide) {
          this.DOMNode.style.display = "none";
        } else if (aAction == kShow) {
          this.DOMNode.style.display = "block";
        } else {
          this.IFrameContainerDOMNode.removeChild(this.DOMNode);
        }
      }

      this.finalCheck = function morphIFrame_finalCheck()
      {
        var accTree = {
          role: ROLE_SECTION,
          children: (aAction == kHide || aAction == kRemove) ? [ ] :
            [
              {
                role: ROLE_INTERNAL_FRAME,
                children: [
                  { role: ROLE_DOCUMENT }
                ]
              }
            ]
        };

        testAccessibleTree(this.IFrameContainerDOMNode, accTree);
      }

      this.getID = function morphIFrame_getID()
      {
        if (aAction == kRemove)
          return "remove iframe";

        return "change display style of iframe to " +
          ((aAction == kHide) ? "none" : "block");
      }
    }

    function makeIFrameVisible(aID)
    {
      this.DOMNode = getNode(aID);

      this.eventSeq = [
        new invokerChecker(EVENT_REORDER, this.DOMNode.parentNode)
      ];

      this.invoke = function makeIFrameVisible_invoke()
      {
        this.DOMNode.style.visibility = "visible";
      }

      this.getID = function makeIFrameVisible_getID()
      {
        return "The accessible for DOM document loaded before it's shown shouldn't have busy state.";
      }
    }

    function openDialogWnd(aURL)
    {
      // Get application root accessible.
      var docAcc = getAccessible(document);
      while (docAcc) {
        this.mRootAcc = docAcc;
        try {
          docAcc = docAcc.parent;
        } catch (e) {
          ok(false, "Can't get parent for " + prettyName(docAcc));
          throw e;
        }
      }

      this.eventSeq = [
        new invokerChecker(EVENT_REORDER, this.mRootAcc)
      ];

      this.invoke = function openDialogWnd_invoke()
      {
        this.mDialog = window.openDialog(aURL);
      }

      this.finalCheck = function openDialogWnd_finalCheck()
      {
        this.finalCheckImpl();
      }

      this.finalCheckImpl = function openDialogWnd_finalCheckImpl()
      {
        var accTree = {
          role: ROLE_APP_ROOT,
          children: [
            {
              role: ROLE_CHROME_WINDOW
            },
            {
              role: ROLE_CHROME_WINDOW
            },
            {
              role: ROLE_CHROME_WINDOW
            },
            {
              role: ROLE_CHROME_WINDOW
            }
          ]
        };

        testAccessibleTree(this.mRootAcc, accTree);

        var dlgDoc = this.mDialog.document;
        ok(isAccessibleInCache(dlgDoc),
           "The document accessible for '" + aURL + "' is not in cache!");

        this.mDialog.close();

        // close() is asynchronous.
        SimpleTest.executeSoon(function() {
          ok(!isAccessibleInCache(dlgDoc),
             "The document accessible for '" + aURL + "' is in cache still!");
        });
      }

      this.getID = function openDialogWnd_getID()
      {
        return "open dialog '" + aURL + "'";
      }
    }

    function openWndShutdownDoc()
    {
      this.__proto__ =
        new openDialogWnd("../events/docload_wnd.html");

      var thisObj = this;
      var docChecker = {
        type: EVENT_HIDE,
        get target()
        {
          var iframe = this.invoker.mDialog.document.getElementById("iframe");
          this.invoker.iframeDoc = iframe.contentDocument;
          return iframe;
        },
        get targetDescr()
        {
          return "inner iframe of docload_wnd.html document";
        },
        invoker: thisObj
      };

      this.eventSeq.push(docChecker);

      this.finalCheck = function openWndShutdownDoc_finalCheck()
      {
        // After timeout after event hide for iframe was handled the document
        // accessible for iframe's document is in cache still.
        ok(!isAccessibleInCache(this.iframeDoc),
            "The document accessible for iframe is in cache still after iframe hide!");

        this.finalCheckImpl();

        // After the window is closed all alive subdocument accessibles should
        // be shut down.
        ok(!isAccessibleInCache(this.iframeDoc),
           "The document accessible for iframe is in cache still!");
      }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Do tests

    var gQueue = null;

    // Debug stuff.
    // gA11yEventDumpID = "eventdump";
    //gA11yEventDumpToConsole = true;

    function doTests()
    {
      gQueue = new eventQueue();

      gQueue.push(new changeIframeSrc("iframe", "about:"));
      gQueue.push(new changeIframeSrc("iframe", "about:buildconfig"));
      gQueue.push(new morphIFrame("iframe", kHide));
      gQueue.push(new morphIFrame("iframe", kShow));
      gQueue.push(new morphIFrame("iframe", kRemove));
      gQueue.push(new makeIFrameVisible("iframe2"));
      gQueue.push(new openDialogWnd("about:"));
      gQueue.push(new openWndShutdownDoc());

      gQueue.onFinish = doLastCallTests;

      gQueue.invoke(); // Will call SimpleTest.finish();
    }

    function doLastCallTests()
    {
      //////////////////////////////////////////////////////////////////////////
      // makeIFrameVisible() test, part2

      // The document shouldn't have busy state (the DOM document was loaded
      // before its accessible was created). Do this test lately to make sure
      // the content of document accessible was created initially, prior to this
      // the document accessible keeps busy state. The initial creation happens
      // asynchronously after document creation, there are no events we could
      // use to catch it.
      var iframeDoc = getAccessible("iframe2").firstChild;
      testStates(iframeDoc, 0, 0, STATE_BUSY);
    }

    SimpleTest.waitForExplicitFinish();
    addA11yLoadEvent(doTests);
  </script>
</head>

<body>

  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=420845"
     title="Fire event_reorder on any embedded frames/iframes whos document has just loaded">
    Mozilla Bug 420845
  </a><br>
  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=506206"
     title="Fire event_reorder application root accessible">
    Mozilla Bug 506206
  </a><br>
  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=566103"
     title="Reorganize accessible document handling">
    Mozilla Bug 566103
  </a><br>
  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=571459"
     title="Shutdown document accessible when presshell goes away">
    Mozilla Bug 571459
  </a>
  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=658185"
     title="The DOM document loaded before it's shown shouldn't have busy state">
    Mozilla Bug 658185
  </a>
  <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=754165"
     title="Fire document load events on iframes too">
    Mozilla Bug 754165
  </a>

  <p id="display"></p>
  <div id="content" style="display: none"></div>
  <pre id="test">
  </pre>

  <div id="testContainer"><iframe id="iframe"></iframe></div>
  <div id="testContainer2"><iframe id="iframe2" src="about:" style="visibility: hidden;"></iframe></div>
  <div id="eventdump"></div>
</body>
</html>
